import 'dart:ui';

import 'package:flutter/material.dart';

/// DateFormat.
enum DateFormat {
  ///yyyy-MM-dd HH:mm:ss.SSS
  DEFAULT,

  ///yyyy-MM-dd HH:mm:ss
  NORMAL,

  ///yyyy-MM-dd HH:mm
  YEAR_MONTH_DAY_HOUR_MINUTE,

  ///yyyy-MM-dd
  YEAR_MONTH_DAY,

  ///yyyy-MM
  YEAR_MONTH,

  ///MM-dd
  MONTH_DAY,

  ///MM-dd HH:mm
  MONTH_DAY_HOUR_MINUTE,

  ///HH:mm:ss
  HOUR_MINUTE_SECOND,

  ///HH:mm
  HOUR_MINUTE,

  ///yyyy年MM月dd日 HH时mm分ss秒SSS毫秒
  ZH_DEFAULT,

  ///yyyy年MM月dd日 HH时mm分ss秒  /  timeSeparate: ":" --> yyyy年MM月dd日 HH:mm:ss
  ZH_NORMAL,

  ///yyyy年MM月dd日 HH时mm分  /  timeSeparate: ":" --> yyyy年MM月dd日 HH:mm
  ZH_YEAR_MONTH_DAY_HOUR_MINUTE,

  ///yyyy年MM月dd日
  ZH_YEAR_MONTH_DAY,

  ///yyyy年MM月
  ZH_YEAR_MONTH,

  ///MM月dd日
  ZH_MONTH_DAY,

  ///MM月dd日 HH时mm分  /  timeSeparate: ":" --> MM月dd日 HH:mm
  ZH_MONTH_DAY_HOUR_MINUTE,

  ///HH时mm分ss秒
  ZH_HOUR_MINUTE_SECOND,

  ///HH时mm分
  ZH_HOUR_MINUTE,
}

// ignore: avoid_classes_with_only_static_members
/// 一些常用格式参照。可以自定义格式，例如："yyyy/MM/dd HH:mm:ss"，"yyyy/M/d HH:mm:ss"。
/// 格式要求
/// year -> yyyy/yy   month -> MM/M    day -> dd/d
/// hour -> HH/H      minute -> mm/m   second -> ss/s

class DateFormats {
  ///yyyy-MM-dd HH:mm:ss
  static String full = 'yyyy-MM-dd HH:mm:ss';

  ///yyyy-MM-dd HH:mm
  // ignore: non_constant_identifier_names
  static String y_mo_d_h_m = 'yyyy-MM-dd HH:mm';

  ///yyyy-MM-dd
  // ignore: non_constant_identifier_names
  static String y_mo_d = 'yyyy-MM-dd';

  ///yyyy-MM
  // ignore: non_constant_identifier_names
  static String y_mo = 'yyyy-MM';

  ///MM-dd
  // ignore: non_constant_identifier_names
  static String mo_d = 'MM-dd';

  ///MM-dd HH:mm
  // ignore: non_constant_identifier_names
  static String mo_d_h_m = 'MM-dd HH:mm';

  ///HH:mm:ss
  // ignore: non_constant_identifier_names
  static String h_m_s = 'HH:mm:ss';

  ///HH:mm
  // ignore: non_constant_identifier_names
  static String h_m = 'HH:mm';

  ///yyyy年MM月dd日 HH时mm分ss秒
// ignore: non_constant_identifier_names
  static String zh_full = 'yyyy年MM月dd日 HH时mm分ss秒';

  ///yyyy年MM月dd日 HH时mm分
  // ignore: non_constant_identifier_names
  static String zh_y_mo_d_h_m = 'yyyy年MM月dd日 HH时mm分';

  ///yyyy年MM月dd日
  // ignore: non_constant_identifier_names
  static String zh_y_mo_d = 'yyyy年MM月dd日';

  ///yyyy年MM月
  // ignore: non_constant_identifier_names
  static String zh_y_mo = 'yyyy年MM月';

  ///MM月dd日
  // ignore: non_constant_identifier_names
  static String zh_mo_d = 'MM月dd日';

  ///MM月dd日 HH时mm分
  // ignore: non_constant_identifier_names
  static String zh_mo_d_h_m = 'MM月dd日 HH时mm分';

  ///HH时mm分ss秒
  // ignore: non_constant_identifier_names
  static String zh_h_m_s = 'HH时mm分ss秒';

  ///HH时mm分
  // ignore: non_constant_identifier_names
  static String zh_h_m = 'HH时mm分';
}

///  默认格式 yyyy-MM-dd
String defaultFormatDate(int milliseconds) {
  return DateUtil.formatDateMs(milliseconds, format: DateFormats.y_mo_d);
}

///默认格式 yyyy-MM-dd
String defaultFormattingStyleForDate(DateTime dateTime) {
  return DateUtil.formatDateMs(dateTime.millisecondsSinceEpoch,
      format: DateFormats.y_mo_d);
}

///默认格式 yyyy-MM-dd
DateTime? defaultFormatDateStr(String date) {
  return DateUtil.getDateTime(date);
}

///默认格式 yyyy-MM-dd HH:mm
String defaultFormatDateTime(int milliseconds) {
  return DateUtil.formatDateMs(milliseconds, format: DateFormats.y_mo_d_h_m);
}

///默认中文格式 yyyy年MM月dd日
String defaultFormatDateZH(int milliseconds) {
  return DateUtil.formatDateMs(milliseconds, format: DateFormats.zh_y_mo_d);
}

///默认中文格式 yyyy年MM月dd日
String defaultFormatDateTimeZH(int milliseconds) {
  return DateUtil.formatDateMs(milliseconds, format: DateFormats.zh_y_mo_d_h_m);
}

/// Date Util.
class DateUtil {
  ///1秒
  static const int second = 1000;

  ///1分钟
  static const int minute = 60 * second;

  ///1小时
  static const int hour = 60 * minute;

  ///1天
  static const int oneDay = 24 * hour;

  ///一个月 以30天为准
  static const int month = 30 * oneDay;

  ///一年
  static const int year = 12 * month;

  ///获取星座
  static String getConstellation(DateTime birthday) {
    const String capricorn = '摩羯座'; //Capricorn 摩羯座（12月22日～1月20日）
    const String aquarius = '水瓶座'; //Aquarius 水瓶座（1月21日～2月19日）
    const String pisces = '双鱼座'; //Pisces 双鱼座（2月20日～3月20日）
    const String aries = '白羊座'; //3月21日～4月20日
    const String taurus = '金牛座'; //4月21～5月21日
    const String gemini = '双子座'; //5月22日～6月21日
    const String cancer = '巨蟹座'; //Cancer 巨蟹座（6月22日～7月22日）
    const String leo = '狮子座'; //Leo 狮子座（7月23日～8月23日）
    const String virgo = '处女座'; //Virgo 处女座（8月24日～9月23日）
    const String libra = '天秤座'; //Libra 天秤座（9月24日～10月23日）
    const String scorpio = '天蝎座'; //Scorpio 天蝎座（10月24日～11月22日）
    const String sagittarius = '射手座'; //Sagittarius 射手座（11月23日～12月21日）

    final int month = birthday.month;
    final int day = birthday.day;
    String constellation = '';

    switch (month) {
      case DateTime.january:
        constellation = day < 21 ? capricorn : aquarius;
        break;
      case DateTime.february:
        constellation = day < 20 ? aquarius : pisces;
        break;
      case DateTime.march:
        constellation = day < 21 ? pisces : aries;
        break;
      case DateTime.april:
        constellation = day < 21 ? aries : taurus;
        break;
      case DateTime.may:
        constellation = day < 22 ? taurus : gemini;
        break;
      case DateTime.june:
        constellation = day < 22 ? gemini : cancer;
        break;
      case DateTime.july:
        constellation = day < 23 ? cancer : leo;
        break;
      case DateTime.august:
        constellation = day < 24 ? leo : virgo;
        break;
      case DateTime.september:
        constellation = day < 24 ? virgo : libra;
        break;
      case DateTime.october:
        constellation = day < 24 ? libra : scorpio;
        break;
      case DateTime.november:
        constellation = day < 23 ? scorpio : sagittarius;
        break;
      case DateTime.december:
        constellation = day < 22 ? sagittarius : capricorn;
        break;
    }

    return constellation;
  }

  ///倒计时
  static String countdown(int time) {
    final int h = time ~/ hour;
    final int allMinute = time - h * hour;
    final int m = allMinute ~/ minute;
    final int allSecond = allMinute - m * minute;
    final int s = allSecond ~/ second;

    ///当为个位数时 数字坐标补0
    return '${h < 10 ? '0$h' : h}:${m < 10 ? '0$m' : m}:${s < 10 ? '0$s' : s}';
  }

  ///获取多少分钟前
  static String getTimeAgoStr(int time) {
    final int now = getNowDateMs();
    final int diff = now - time;
    if (diff < oneDay) {
      return getDateStrByMs(time, format: DateFormat.HOUR_MINUTE);
    } else if (diff >= oneDay && diff < year) {
      return getDateStrByMs(time, format: DateFormat.MONTH_DAY);
    } else {
      return getDateStrByMs(time, format: DateFormat.YEAR_MONTH_DAY);
    }
  }

  ///获取多少分钟前
  static String getTimeAgo(int time) {
    final int now = getNowDateMs();
    final int diff = now - time;
    if (diff < minute) {
      return '刚刚';
    } else if (diff >= minute && diff < hour) {
      final int t = diff ~/ minute;
      return '$t分钟前';
    } else if (diff >= hour && diff < oneDay) {
      final int t = diff ~/ hour;
      return '$t小时前';
    } else if (diff >= oneDay && diff < month) {
      final int t = diff ~/ oneDay;
      return '$t天前';
    } else {
      return getDateStrByMs(time, format: DateFormat.ZH_YEAR_MONTH_DAY);
    }
  }

  /// get DateTime By DateStr.
  static DateTime? getDateTime(String dateStr, {bool isUtc = false}) {
    DateTime? dateTime = DateTime.tryParse(dateStr);
    if (isUtc) {
      dateTime = dateTime?.toUtc();
    } else {
      dateTime = dateTime?.toLocal();
    }
    return dateTime;
  }

  ///字符串年龄转 int
  static int getAgeByDateStr(String birthDayDateStr) {
    final DateTime? birthDay = getDateTime(birthDayDateStr);
    if (birthDay != null) {
      return getAge(birthDay);
    }
    return -1;
  }

  ///dateTime年龄转 int
  static int getAge(DateTime birthday) {
    final int yearDiff = DateTime.now().year - birthday.year;
    bool birthdayPastFlag = false;
    final int monDiff = DateTime.now().month - birthday.month;
    final int dayDiff = DateTime.now().day - birthday.day;
    if (monDiff > 0 || (monDiff == 0 && dayDiff >= 0)) {
      birthdayPastFlag = true;
    }
    if (birthdayPastFlag) {
      return yearDiff;
    } else {
      return yearDiff - 1;
    }
  }

  /// get DateTime By Milliseconds.
  static DateTime getDateTimeByMs(int milliseconds, {bool isUtc = false}) {
    return DateTime.fromMillisecondsSinceEpoch(milliseconds, isUtc: isUtc);
  }

  /// get DateMilliseconds By DateStr.
  static int? getDateMsByTimeStr(String dateStr) {
    final DateTime? dateTime = DateTime.tryParse(dateStr);
    return dateTime?.millisecondsSinceEpoch;
  }

  /// get Now Date Milliseconds.
  static int getNowDateMs() {
    return DateTime.now().millisecondsSinceEpoch;
  }

  /// get Now Date Str.(yyyy-MM-dd HH:mm:ss)
  static String getNowDateStr() {
    return getDateStrByDateTime(DateTime.now());
  }

  /// get DateStr By DateStr.
  /// dateStr         date String.
  /// format          DateFormat type.
  /// dateSeparate    date separate.
  /// timeSeparate    time separate.
  static String getDateStrByTimeStr(
    String dateStr, {
    DateFormat format = DateFormat.NORMAL,
    String? dateSeparate,
    String? timeSeparate,
    bool isUtc = false,
  }) {
    final DateTime? dateTime = getDateTime(dateStr, isUtc: isUtc);

    return getDateStrByDateTime(dateTime,
        format: format, dateSeparate: dateSeparate, timeSeparate: timeSeparate);
  }

  /// get DateStr By Milliseconds.
  /// milliseconds    milliseconds.
  /// format          DateFormat type.
  /// dateSeparate    date separate.
  /// timeSeparate    time separate.
  static String getDateStrByMs(int milliseconds,
      {DateFormat format = DateFormat.NORMAL,
      String? dateSeparate,
      String? timeSeparate,
      bool isUtc = false}) {
    final DateTime dateTime = getDateTimeByMs(milliseconds, isUtc: isUtc);
    return getDateStrByDateTime(dateTime,
        format: format, dateSeparate: dateSeparate, timeSeparate: timeSeparate);
  }

  /// get DateStr By DateTime.
  /// dateTime        dateTime.
  /// format          DateFormat type.
  /// dateSeparate    date separate.
  /// timeSeparate    time separate.
  static String getDateStrByDateTime(DateTime? dateTime,
      {DateFormat format = DateFormat.NORMAL,
      String? dateSeparate,
      String? timeSeparate}) {
    if (dateTime == null) {
      return '';
    }
    String dateStr = dateTime.toString();
    if (isZHFormat(format)) {
      dateStr = formatZHDateTime(dateStr, format, timeSeparate);
    } else {
      dateStr = formatDateTime(dateStr, format, dateSeparate, timeSeparate);
    }
    return dateStr;
  }

  /// format ZH DateTime.
  /// time            time string.
  /// format          DateFormat type.
  ///timeSeparate    time separate.
  static String formatZHDateTime(
      String time, DateFormat format, String? timeSeparate) {
    time = convertToZHDateTimeString(time, timeSeparate);
    switch (format) {
      case DateFormat.ZH_NORMAL: //yyyy年MM月dd日 HH时mm分ss秒
        time = time.substring(
            0,
            'yyyy年MM月dd日 HH时mm分ss秒'.length -
                (timeSeparate == null || timeSeparate.isEmpty ? 0 : 1));
        break;
      case DateFormat.ZH_YEAR_MONTH_DAY_HOUR_MINUTE: //yyyy年MM月dd日 HH时mm分
        time = time.substring(
            0,
            'yyyy年MM月dd日 HH时mm分'.length -
                (timeSeparate == null || timeSeparate.isEmpty ? 0 : 1));
        break;
      case DateFormat.ZH_YEAR_MONTH_DAY: //yyyy年MM月dd日
        time = time.substring(0, 'yyyy年MM月dd日'.length);
        break;
      case DateFormat.ZH_YEAR_MONTH: //yyyy年MM月
        time = time.substring(0, 'yyyy年MM月'.length);
        break;
      case DateFormat.ZH_MONTH_DAY: //MM月dd日
        time = time.substring('yyyy年'.length, 'yyyy年MM月dd日'.length);
        break;
      case DateFormat.ZH_MONTH_DAY_HOUR_MINUTE: //MM月dd日 HH时mm分
        time = time.substring(
            'yyyy年'.length,
            'yyyy年MM月dd日 HH时mm分'.length -
                (timeSeparate == null || timeSeparate.isEmpty ? 0 : 1));
        break;
      case DateFormat.ZH_HOUR_MINUTE_SECOND: //HH时mm分ss秒
        time = time.substring(
            'yyyy年MM月dd日 '.length,
            'yyyy年MM月dd日 HH时mm分ss秒'.length -
                (timeSeparate == null || timeSeparate.isEmpty ? 0 : 1));
        break;
      case DateFormat.ZH_HOUR_MINUTE: //HH时mm分
        time = time.substring(
            'yyyy年MM月dd日 '.length,
            'yyyy年MM月dd日 HH时mm分'.length -
                (timeSeparate == null || timeSeparate.isEmpty ? 0 : 1));
        break;
      default:
        break;
    }
    return time;
  }

  /// format DateTime.
  /// time            time string.
  /// format          DateFormat type.
  /// dateSeparate    date separate.
  /// timeSeparate    time separate.
  static String formatDateTime(String time, DateFormat format,
      String? dateSeparate, String? timeSeparate) {
    switch (format) {
      case DateFormat.NORMAL: //yyyy-MM-dd HH:mm:ss
        time = time.substring(0, 'yyyy-MM-dd HH:mm:ss'.length);
        break;
      case DateFormat.YEAR_MONTH_DAY_HOUR_MINUTE: //yyyy-MM-dd HH:mm
        time = time.substring(0, 'yyyy-MM-dd HH:mm'.length);
        break;
      case DateFormat.YEAR_MONTH_DAY: //yyyy-MM-dd
        time = time.substring(0, 'yyyy-MM-dd'.length);
        break;
      case DateFormat.YEAR_MONTH: //yyyy-MM
        time = time.substring(0, 'yyyy-MM'.length);
        break;
      case DateFormat.MONTH_DAY: //MM-dd
        time = time.substring('yyyy-'.length, 'yyyy-MM-dd'.length);
        break;
      case DateFormat.MONTH_DAY_HOUR_MINUTE: //MM-dd HH:mm
        time = time.substring('yyyy-'.length, 'yyyy-MM-dd HH:mm'.length);
        break;
      case DateFormat.HOUR_MINUTE_SECOND: //HH:mm:ss
        time =
            time.substring('yyyy-MM-dd '.length, 'yyyy-MM-dd HH:mm:ss'.length);
        break;
      case DateFormat.HOUR_MINUTE: //HH:mm
        time = time.substring('yyyy-MM-dd '.length, 'yyyy-MM-dd HH:mm'.length);
        break;
      default:
        break;
    }
    time = dateTimeSeparate(time, dateSeparate, timeSeparate);
    return time;
  }

  /// is format to ZH DateTime String
  static bool isZHFormat(DateFormat format) {
    return format == DateFormat.ZH_DEFAULT ||
        format == DateFormat.ZH_NORMAL ||
        format == DateFormat.ZH_YEAR_MONTH_DAY_HOUR_MINUTE ||
        format == DateFormat.ZH_YEAR_MONTH_DAY ||
        format == DateFormat.ZH_YEAR_MONTH ||
        format == DateFormat.ZH_MONTH_DAY ||
        format == DateFormat.ZH_MONTH_DAY_HOUR_MINUTE ||
        format == DateFormat.ZH_HOUR_MINUTE_SECOND ||
        format == DateFormat.ZH_HOUR_MINUTE;
  }

  /// convert To ZH DateTime String
  static String convertToZHDateTimeString(String time, String? timeSeparate) {
    time = time.replaceFirst('-', '年');
    time = time.replaceFirst('-', '月');
    time = time.replaceFirst(' ', '日 ');
    if (timeSeparate == null || timeSeparate.isEmpty) {
      time = time.replaceFirst(':', '时');
      time = time.replaceFirst(':', '分');
      time = time.replaceFirst('.', '秒');
      time = time + '毫秒';
    } else {
      time = time.replaceAll(':', timeSeparate);
    }
    return time;
  }

  /// date Time Separate.
  static String dateTimeSeparate(
      String time, String? dateSeparate, String? timeSeparate) {
    if (dateSeparate != null) {
      time = time.replaceAll('-', dateSeparate);
    }
    if (timeSeparate != null) {
      time = time.replaceAll(':', timeSeparate);
    }
    return time;
  }

  /// format date by milliseconds.
  /// milliseconds 日期毫秒
  static String formatDateMs(int milliseconds,
      {bool isUtc = false, String? format}) {
    return formatDate(getDateTimeByMs(milliseconds, isUtc: isUtc),
        format: format);
  }

  /// format date by date str.
  /// dateStr 日期字符串
  static String formatDateStr(String dateStr,
      {bool isUtc = false, String? format}) {
    return formatDate(getDateTime(dateStr, isUtc: isUtc), format: format);
  }

  /// format date by DateTime.
  /// format 转换格式(已提供常用格式 DataFormats，可以自定义格式："yyyy/MM/dd HH:mm:ss")
  /// 格式要求
  /// year -> yyyy/yy   month -> MM/M    day -> dd/d
  /// hour -> HH/H      minute -> mm/m   second -> ss/s
  static String formatDate(DateTime? dateTime,
      {bool isUtc = false, String? format}) {
    if (dateTime == null) {
      return '';
    }
    format = format ?? DateFormats.full;
    if (format.contains('yy')) {
      final String year = dateTime.year.toString();
      if (format.contains('yyyy')) {
        format = format.replaceAll('yyyy', year);
      } else {
        format = format.replaceAll(
            'yy', year.substring(year.length - 2, year.length));
      }
    }

    format = _comFormat(dateTime.month, format, 'M', 'MM');
    format = _comFormat(dateTime.day, format, 'd', 'dd');
    format = _comFormat(dateTime.hour, format, 'H', 'HH');
    format = _comFormat(dateTime.minute, format, 'm', 'mm');
    format = _comFormat(dateTime.second, format, 's', 'ss');
    format = _comFormat(dateTime.millisecond, format, 'S', 'SSS');

    return format;
  }

  /// com format.
  static String _comFormat(
      int value, String format, String single, String full) {
    if (format.contains(single)) {
      if (format.contains(full)) {
        format =
            format.replaceAll(full, value < 10 ? '0$value' : value.toString());
      } else {
        format = format.replaceAll(single, value.toString());
      }
    }
    return format;
  }

  /// get WeekDay By Milliseconds.
  static String getWeekDayByMs(int milliseconds, {bool isUtc = false}) {
    final DateTime dateTime = getDateTimeByMs(milliseconds, isUtc: isUtc);
    return getWeekDay(dateTime);
  }

  /// get ZH WeekDay By Milliseconds.
  static String getZHWeekDayByMs(int milliseconds, {bool isUtc = false}) {
    final DateTime dateTime = getDateTimeByMs(milliseconds, isUtc: isUtc);
    return getZHWeekDay(dateTime);
  }

  /// get WeekDay.
  static String getWeekDay(DateTime? dateTime) {
    if (dateTime == null) {
      return '';
    }
    String weekday;
    switch (dateTime.weekday) {
      case 1:
        weekday = 'Monday';
        break;
      case 2:
        weekday = 'Tuesday';
        break;
      case 3:
        weekday = 'Wednesday';
        break;
      case 4:
        weekday = 'Thursday';
        break;
      case 5:
        weekday = 'Friday';
        break;
      case 6:
        weekday = 'Saturday';
        break;
      case 7:
        weekday = 'Sunday';
        break;
      default:
        weekday = '';
        break;
    }
    return weekday;
  }

  /// get ZH WeekDay.
  static String getZHWeekDay(DateTime? dateTime) {
    if (dateTime == null) {
      return '';
    }
    String weekday;
    switch (dateTime.weekday) {
      case 1:
        weekday = '星期一';
        break;
      case 2:
        weekday = '星期二';
        break;
      case 3:
        weekday = '星期三';
        break;
      case 4:
        weekday = '星期四';
        break;
      case 5:
        weekday = '星期五';
        break;
      case 6:
        weekday = '星期六';
        break;
      case 7:
        weekday = '星期日';
        break;
      default:
        weekday = '';
        break;
    }
    return weekday;
  }

  /// Return whether it is leap year.
  static bool isLeapYearByDateTime(DateTime dateTime) {
    return isLeapYearByYear(dateTime.year);
  }

  /// Return whether it is leap year.
  static bool isLeapYearByYear(int year) {
    return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
  }

  /// is yesterday by millis.
  /// 是否是昨天.
  static bool isYesterdayByMillis(int millis, int locMillis) {
    return isYesterday(DateTime.fromMillisecondsSinceEpoch(millis),
        DateTime.fromMillisecondsSinceEpoch(locMillis));
  }

  /// is yesterday by dateTime.
  /// 是否是昨天.
  static bool isYesterday(DateTime dateTime, DateTime locDateTime) {
    if (yearIsEqual(dateTime, locDateTime)) {
      final int spDay = getDayOfYear(locDateTime) - getDayOfYear(dateTime);
      return spDay == 1;
    } else {
      return locDateTime.year - dateTime.year == 1 &&
          dateTime.month == 12 &&
          locDateTime.month == 1 &&
          dateTime.day == 31 &&
          locDateTime.day == 1;
    }
  }

  /// get day of year.
  /// 在今年的第几天.
  static int getDayOfYearByMillis(int millis, {bool isUtc = false}) {
    return getDayOfYear(
        DateTime.fromMillisecondsSinceEpoch(millis, isUtc: isUtc));
  }

  /// get day of year.
  /// 在今年的第几天.
  static int getDayOfYear(DateTime dateTime) {
    final int year = dateTime.year;
    final int month = dateTime.month;
    int days = dateTime.day;

    ///遍历到上一个月
    for (int i = 1; i < month; i++) {
      final int? value = getDaysInMonth(year, month);
      days = days + value!;
    }
    return days;
  }

  /// year is equal.
  /// 是否同年.
  static bool yearIsEqualByMillis(int millis, int locMillis) {
    return yearIsEqual(DateTime.fromMillisecondsSinceEpoch(millis),
        DateTime.fromMillisecondsSinceEpoch(locMillis));
  }

  /// year is equal.
  /// 是否同年.
  static bool yearIsEqual(DateTime dateTime, DateTime locDateTime) {
    return dateTime.year == locDateTime.year;
  }

  /// is today.
  /// 是否是当天.
  static bool isToday(int milliseconds, {bool isUtc = false}) {
    if (milliseconds == 0) {
      return false;
    }
    final DateTime old =
        DateTime.fromMillisecondsSinceEpoch(milliseconds, isUtc: isUtc);
    final DateTime now =
        isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal();
    return old.year == now.year && old.month == now.month && old.day == now.day;
  }

  /// is Week.
  /// 是否是本周.
  static bool isWeek(int milliseconds, {bool isUtc = false}) {
    if (milliseconds <= 0) {
      return false;
    }
    final DateTime _old =
        DateTime.fromMillisecondsSinceEpoch(milliseconds, isUtc: isUtc);
    final DateTime _now =
        isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal();
    final DateTime old =
        _now.millisecondsSinceEpoch > _old.millisecondsSinceEpoch ? _old : _now;
    final DateTime now =
        _now.millisecondsSinceEpoch > _old.millisecondsSinceEpoch ? _now : _old;
    return (now.weekday >= old.weekday) &&
        (now.millisecondsSinceEpoch - old.millisecondsSinceEpoch <=
            7 * 24 * 60 * 60 * 1000);
  }
}

///每行的高度
const double dayRowHeight = 42.0;

///最大行数
const int maxDayRowCount = 6;

///周的最大行数
const int maxWeekRowCount = 1;

///总的条目数量
const int allItemCount = DateTime.daysPerWeek * maxDayRowCount;

///获取指定月份第一天与周日的的间隔
int firstDayOffset(int year, int month, MaterialLocalizations localizations) {
  // 0-based day of week for the month and year, with 0 representing Monday.
  final int weekdayFromMonday = DateTime(year, month).weekday - 1;

  // 0-based start of week depending on the locale, with 0 representing Sunday.
  int firstDayOfWeekIndex = localizations.firstDayOfWeekIndex;

  // firstDayOfWeekIndex recomputed to be Monday-based, in order to compare with
  // weekdayFromMonday.
  firstDayOfWeekIndex = (firstDayOfWeekIndex - 1) % 7;

  // Number of days between the first day of week appearing on the calendar,
  // and the day corresponding to the first of the month.
  return (weekdayFromMonday - firstDayOfWeekIndex) % 7;
}

///获取某年的某个月的天数
int getDaysInMonth(int year, int month) {
  if (month == DateTime.february) {
    final bool isLeapYear =
        (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
    if (isLeapYear) {
      return 29;
    }
    return 28;
  }
  const List<int> daysInMonth = <int>[
    31,
    -1,
    31,
    30,
    31,
    30,
    31,
    31,
    30,
    31,
    30,
    31
  ];
  return daysInMonth[month - 1];
}

///获取上一个月
DateTime previous(DateTime dateTime) {
  int month = dateTime.month - 1;
  int year = dateTime.year;
  int day = dateTime.day;
  if (month == 0) {
    month = 12;
    year = year - 1;
  }

  final int days = getDaysInMonth(year, month);
  if (day > days) {
    day = days;
  }

  return DateTime(year, month, day);
}

///获取下一个月
DateTime next(DateTime dateTime) {
  int month = dateTime.month + 1;
  int year = dateTime.year;
  int day = dateTime.day;
  if (month == 13) {
    month = 1;
    year = year + 1;
  }

  final int days = getDaysInMonth(year, month);
  if (day > days) {
    day = days;
  }

  return DateTime(year, month);
}

///是否为同一天
bool isSameDay(DateTime dateA, DateTime dateB) {
  return dateA.year == dateB.year &&
      dateA.month == dateB.month &&
      dateA.day == dateB.day;
}

///日历头，日、一、二、三、四、五、六
List<Widget> dayHeaders(
    TextStyle headerStyle, MaterialLocalizations localizations) {
  final List<Widget> result = <Widget>[];
  TextStyle style = headerStyle;
  for (int i = localizations.firstDayOfWeekIndex; true; i = (i + 1) % 7) {
    final String weekday = localizations.narrowWeekdays[i];

    if (i == 0 || i == 6) {
      // style = headerStyle.copyWith(color: Colors.red.shade300);
      style = headerStyle;
    } else {
      style = headerStyle;
    }
    result.add(ExcludeSemantics(
      child: Center(child: Text(weekday, style: style)),
    ));
    if (i == (localizations.firstDayOfWeekIndex - 1) % 7) {
      break;
    }
  }
  return result;
}
